﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XLua;

namespace com.yoozoo.gta.Extension
{
    public class DragScaleScrollRect : ScrollRect, IPointerClickHandler
    {
        public bool _DragScaleOpen = true;
        public float _DefaultScale = 2f;
        public float _MinScale = 1f;
        public float _MaxScale = 5;
        public float _ScaleSensitivity = 0.5f;
        private Touch oldTouch1;  
        private Touch oldTouch2;  
        private int touchNum = 0;
        public Action<float> onContentScaleChanged;
        public Action onBeginDrag;
        public Action onDrag;
        public Action onEndDrag;
        public Action onClick;
        
        protected override void Awake()
        {
            base.Awake();

            content.localScale = new Vector3(_DefaultScale, _DefaultScale, _DefaultScale);
        }

        public void OnPointerClick(PointerEventData eventData)
        {
            onClick?.Invoke();
        }
        
        public override void OnBeginDrag(PointerEventData eventData)
        {
            if (Input.touchCount > 1)
            {
                return;
            }

            base.OnBeginDrag(eventData);
            onBeginDrag?.Invoke();
        }

        public override void OnDrag(PointerEventData eventData)
        {
            if (Input.touchCount > 1)
            {
                touchNum = Input.touchCount;
                return;
            }
            else if (Input.touchCount == 1 && touchNum > 1)
            {
                touchNum = Input.touchCount;
                base.OnBeginDrag(eventData);
                return;
            }

            base.OnDrag(eventData);
            onDrag?.Invoke();
        }

        public override void OnEndDrag(PointerEventData eventData)
        {
            base.OnEndDrag(eventData);
            // 刷新轴心
            UpdatePivot();
            onEndDrag?.Invoke();
        }

        // 刷新轴心
        public void UpdatePivot()
        {
            // 模拟了一次拖拽，因为ScrollRect的LateUpdate在MovementType.Clamped的模式下，会去调用CalculateOffset计算Content偏移，
            // 从而导致Content被赋予不合理范围的anchoredPosition和pivot（虽然位置不会改变）。这里用拖拽模拟是CalculateOffset的访问权限问题
            {
                PointerEventData eventData = new PointerEventData(EventSystem.current);
                eventData.Reset();
                eventData.position = Vector2.zero;
                eventData.clickCount = 1;
                eventData.button = PointerEventData.InputButton.Left;
                base.OnBeginDrag(eventData);
                base.OnDrag(eventData);
                base.OnEndDrag(eventData);
            }
            
            // 当前content真实大小 (算上缩放)
            Vector2 contentRealSize = content.sizeDelta * content.localScale.x;
            Vector2 contentAnchoredPosition = content.anchoredPosition;
            // viewport中心点在content中的normalizedPosition
            Vector2 viewportCenterPivot = new Vector2(((contentRealSize.x*content.pivot.x)-contentAnchoredPosition.x) / contentRealSize.x,
                ((contentRealSize.y*content.pivot.y)-contentAnchoredPosition.y) / contentRealSize.y);
            // 处理缩到极限小的情况
            if (contentRealSize.x <= viewport.rect.width)
            {
                viewportCenterPivot.x = 0.5f;
            }
            if (contentRealSize.y <= viewport.rect.height)
            {
                viewportCenterPivot.y = 0.5f;
            }
            // 修改轴心，且不改变位置
            {
                var pos = content.anchoredPosition;
                pos.x -= contentRealSize.x * (content.pivot.x - viewportCenterPivot.x);
                pos.y -= contentRealSize.y * (content.pivot.y - viewportCenterPivot.y);
                content.pivot = viewportCenterPivot;
                content.anchoredPosition = pos;
            }
        }

        public override void OnScroll(PointerEventData data)
        {
            if (base.content == null) return;
            if (_DragScaleOpen)
            {
                Vector2 delta = data.scrollDelta;
                Vector3 localScale = base.content.transform.localScale;
                float scaleFactor = delta.y * scrollSensitivity * _ScaleSensitivity;
                float scale = localScale.x + scaleFactor;
                //在什么情况下进行缩放
                if (scale > _MaxScale)
                {
                    scale = _MaxScale;
                }
                else if (scale < _MinScale)
                {
                    scale = _MinScale;
                }
                base.content.transform.localScale = new Vector3(scale, scale, scale);
                onContentScaleChanged?.Invoke(scale);

                UpdatePivot();
            }
        }

        void SetPivotByTouches(Touch touch1, Touch touch2)
        {
            Vector2 center = (touch1.position + touch2.position) / 2f;
            Vector2 offset = new Vector2(center.x - Screen.width / 2f, center.y - Screen.height / 2f);
            // 当前content真实大小 (算上缩放)
            Vector2 contentRealSize = content.sizeDelta * content.localScale.x;
            Vector2 contentAnchoredPosition = content.anchoredPosition;
            // viewport中心点在content中的normalizedPosition
            Vector2 viewportCenterPivot = new Vector2(((contentRealSize.x*content.pivot.x)-contentAnchoredPosition.x) / contentRealSize.x,
                ((contentRealSize.y*content.pivot.y)-contentAnchoredPosition.y) / contentRealSize.y);
            // 偏移量
            viewportCenterPivot += new Vector2(offset.x / contentRealSize.x, offset.y / contentRealSize.y);
            // 处理缩到极限小的情况
            if (contentRealSize.x <= viewport.rect.width)
            {
                viewportCenterPivot.x = 0.5f;
            }
            if (contentRealSize.y <= viewport.rect.height)
            {
                viewportCenterPivot.y = 0.5f;
            }
            // 修改轴心，且不改变位置
            {
                var pos = content.anchoredPosition;
                pos.x -= contentRealSize.x * (content.pivot.x - viewportCenterPivot.x);
                pos.y -= contentRealSize.y * (content.pivot.y - viewportCenterPivot.y);
                content.pivot = viewportCenterPivot;
                content.anchoredPosition = pos;
            }
        }
        
        void Update()
        {
            if (base.content == null) return;
            if (_DragScaleOpen)
            {
                if (Input.touchCount >= 2)
                {
                    //多点触摸, 放大缩小
                    Touch newTouch1 = Input.GetTouch(0);
                    Touch newTouch2 = Input.GetTouch(1);
                    //第2点刚开始接触屏幕, 只记录，不做处理
                    if (newTouch2.phase == TouchPhase.Began)
                    {
                        oldTouch2 = newTouch2;
                        oldTouch1 = newTouch1;
                        SetPivotByTouches(newTouch1, newTouch2);
                        return;
                    }
                    //计算老的两点距离和新的两点间距离，变大要放大模型，变小要缩放模型
                    float oldDistance = Vector2.Distance(oldTouch1.position, oldTouch2.position);
                    float newDistance = Vector2.Distance(newTouch1.position, newTouch2.position);
                    //两个距离之差，为正表示放大手势， 为负表示缩小手势
                    float offset = newDistance - oldDistance;
                    //放大因子， 一个像素按 0.01倍来算(100可调整)
                    float scaleFactor = offset / 100f * _ScaleSensitivity;
                    Vector3 localScale = base.content.transform.localScale;
                    float scale = localScale.x + scaleFactor;
                    //在什么情况下进行缩放
                    if (scale > _MaxScale)
                    {
                        scale = _MaxScale;
                    }
                    else if (scale < _MinScale)
                    {
                        scale = _MinScale;
                    }
                    base.content.transform.localScale = new Vector3(scale, scale, scale);
                    onContentScaleChanged?.Invoke(scale);
                    //记住最新的触摸点，下次使用
                    oldTouch1 = newTouch1;
                    oldTouch2 = newTouch2;
                }
            }

        }
    }
}